#include "myScreen.h"

MyScreen::MyScreen()
{
}

MyScreen::~MyScreen()
{
}

void MyScreen::Render()
{
	this->pEngine->GetGraphics()->DrawCamera(this->pMyCamera[this->iViewCamera]);

	this->pEngine->GetGraphics()->EnableDepthTesting();

	for (unsigned int iEntityIndex = 0; iEntityIndex < this->oEntityList.size(); iEntityIndex ++)
		this->pEngine->GetGraphics()->DrawEntity(this->oEntityList[iEntityIndex]);

	this->pEngine->GetGraphics()->DisableDepthTesting();

	this->pEngine->GetGraphics()->Setup2DProjection();

	this->pEngine->GetGraphics()->SetGlobalColor(Color(0, 0, 0, 255));

	stringstream ssText("");
	ssText << "Model Count: " << this->oEntityList.size();
	this->pEngine->GetGraphics()->DrawText(ssText.str(), 10, 10, this->pMyFont);

	ssText = stringstream("");
	ssText << "Models Drawn: " << this->iRenderModelCount;
	this->pEngine->GetGraphics()->DrawText(ssText.str(), 10, 30, this->pMyFont);

	this->pEngine->GetGraphics()->DrawText("Hold [spacebar] to draw all models", 10, this->ScreenHeight() - 45.0f, this->pMyFont);
	this->pEngine->GetGraphics()->DrawText("Press [C] to change camera", 10, this->ScreenHeight() - 25.0f, this->pMyFont);

	this->DrawFpsGraph(this->pEngine->GetGraphics(), (ScreenWidth() / 2.0f) - 200.0f, 10.0f, 400.0f, 100.0f, this->pMyFont);
}

void MyScreen::Update(float fDelta)
{
	AnimatedEntity *pEntity;

	if (fDelta != 0)
	{
		this->fFpsSampleTimer += 20.0f * fDelta;
		if (this->fFpsSampleTimer >= 1)
		{
			this->fFpsSampleTimer = 0;
			this->fCurrentFps = 1.0f / fDelta;
			if (this->fCurrentFps > this->fHighestFps) this->fHighestFps = this->fCurrentFps;

			this->dqSamples.push_front(this->fCurrentFps);
			if (this->dqSamples.size() > 50)
				this->dqSamples.pop_back();
		}
	}

	this->pMyCamera[0]->Turn(0, 10.0f * fDelta, 0);

	Frustum oCameraFrustum = this->pMyCamera[0]->GetFrustum();

	this->iRenderModelCount = 0;
	for (unsigned int iEntityIndex = 0; iEntityIndex < this->oEntityList.size(); iEntityIndex ++)
	{
		pEntity = this->oEntityList[iEntityIndex];

		if (this->pEngine->GetInput()->IsKeyDown(DelGE_Key_Space))
		{
			pEntity->Show();
			this->iRenderModelCount ++;
		}
		else
		{
			pEntity->Hide();
			if (oCameraFrustum.TestShpere(pEntity->GetPosition(), 20.0f))
			{
				pEntity->Show();
				this->iRenderModelCount ++;
			}
		}

		pEntity->UpdateAnimation(fDelta);
	}

	if (this->pEngine->GetInput()->IsKeyHit(DelGE_Key_C))
		this->iViewCamera = 1 - this->iViewCamera;
}

void MyScreen::Load()
{
	this->pMyFont = this->pEngine->GetGraphics()->LoadFont("media/arial.ttf", 14);

	this->pMyCamera[0] = new Camera(0, 0, this->ScreenWidth(), this->ScreenHeight());
	this->pMyCamera[0]->SetPerspectiveProjection(60.0f, 1.33f, 11.0f, 300.0f);
	this->pMyCamera[0]->SetBackgroundColor(Color(255, 189, 38));

	this->pMyCamera[1] = new Camera(0, 0, this->ScreenWidth(), this->ScreenHeight());
	this->pMyCamera[1]->SetPerspectiveProjection(60.0f, 1.33f, 11.0f, 1300.0f);
	this->pMyCamera[1]->SetBackgroundColor(Color(255, 189, 38));
	this->pMyCamera[1]->Turn(-60, 0, 0);
	this->pMyCamera[1]->Move(0, 0, 800);

	this->iViewCamera = 1;
	
	this->pMyTexture = this->pEngine->GetGraphics()->LoadTexture("media/homer.bmp");

	this->pMyBaseEntity = MD2EntityLoader::LoadFromFile("media/homer.md2");
	this->pMyBaseEntity->GetModel(0)->SetTexture(this->pMyTexture);

	this->pMyBaseEntity->AddAnimation("stand", 0, 39, 8);

	AnimatedEntity *pEntity;
	for (int x = -12; x < 13; x ++)
	{
		for (int y = -12; y < 13; y ++)
		{
			pEntity = AnimatedEntity::ShallowCopy(this->pMyBaseEntity);

			pEntity->SetPosition(x * 30.0f, 0, y * 30.0f);
			pEntity->PlayAnimation("stand", DelGEGraphics_Animation_Playstyle_Loop);

			this->oEntityList.push_back(pEntity);
		}
	}

	this->iSampleSize = 50;
	this->dqSamples = deque<float>(iSampleSize);
	this->fCurrentFps = this->fHighestFps = this->fAvarageFps = this->fFpsSampleTimer = 0;
}

void MyScreen::Unload()
{
	this->pMyBaseEntity->Destroy();

	for (unsigned int iEntityIndex = 0; iEntityIndex < this->oEntityList.size(); iEntityIndex ++)
		delete this->oEntityList[iEntityIndex];
	delete this->pMyCamera[0];
	delete this->pMyCamera[1];
	delete this->pMyBaseEntity;
	delete this->pMyTexture;
	delete this->pMyFont;
}

void MyScreen::DrawFpsGraph(GraphicsModule *pGraphics, float x, float y, float width, float height, Font *pFont)
{
	float fAvarageLineY;
	float fSpacing;
	float fSample0, fSample1;
	stringstream sText;
	
	fSpacing = width / (this->iSampleSize - 1.0f);

	pGraphics->SetGlobalColor(0, 0, 0, 155);
	pGraphics->DrawRect(x, y, width, height);

	this->fAvarageFps = 0;

	for (int i = 0; i < this->iSampleSize - 1; i ++)
	{
		fSample0 = fSample1 = 0;

		if (i < this->iSampleSize)		fSample0 = this->dqSamples[i];
		if (i + 1 < this->iSampleSize)	fSample1 = this->dqSamples[i + 1];
		
		this->fAvarageFps += fSample0;
		
		if (fSample0 < this->fHighestFps)
		{
			fSample0 /= this->fHighestFps;
			fSample0 *= height;
		}
		else
		{
			fSample0 = height;
		}

		if (fSample1 < this->fHighestFps)
		{
			fSample1 /= this->fHighestFps;
			fSample1 *= height;
		}
		else
		{
			fSample1 = height;
		}

		pGraphics->SetGlobalColor(55, 55, 55, 100);
		pGraphics->DrawLine((width + x) - (i * fSpacing), y, (width + x) - (i * fSpacing), y + height);


		pGraphics->SetGlobalColor(255, 255, 255, 200);
		pGraphics->DrawLine((width + x) - (i * fSpacing), (height - fSample0) + y, (width + x) - ((i + 1) * fSpacing), (height - fSample1) + y);
	}

	this->fAvarageFps /= this->iSampleSize;

	fAvarageLineY = (height - ((this->fAvarageFps / this->fHighestFps) * height)) + y;

	pGraphics->SetGlobalColor(0, 255, 0, 100);
	pGraphics->DrawLine(x, fAvarageLineY, x + width, fAvarageLineY);

	sText = stringstream("");
	sText << (int)this->fAvarageFps;
	pGraphics->DrawText(sText.str(), x + 5, y + 5, pFont);
}